package com.example.service.impl;

import java.math.BigDecimal;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import javax.servlet.http.HttpServletRequest;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.example.common.HttpStatusConstants;
import com.example.common.R;
import com.example.mapper.AppointmentMapper;
import com.example.mapper.ConEmployeeServiceMapper;
import com.example.mapper.OrderMapper;
import com.example.mapper.RebackMapper;
import com.example.mapper.UserMapper;
import com.example.model.AddOrderDTO;
import com.example.model.req.AddOrderReq;
import com.example.model.resp.ListOrderResp;
import com.example.service.OrderService;
import com.example.utils.JwtUtil;

@Service
public class OrderServiceImpl implements OrderService {
    @Autowired
    private OrderMapper orderMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RebackMapper rebackMapper;
    @Autowired
    private ConEmployeeServiceMapper conEmployeeServiceMapper;
    @Autowired
    private AppointmentMapper appointmentMapper;

    @Override
    public R<String> addOrder(AddOrderReq addOrderReq, HttpServletRequest request) {
        try {
            String openId = JwtUtil.getOpenIdFromToken(request.getHeader("Authorization").replace("Bearer ", ""));
            Integer userId = userMapper.getIdByOpenId(openId);

            AddOrderDTO addOrder = AddOrderDTO.builder()
                    .userId(userId)
                    .serviceId(addOrderReq.getServiceId())
                    .startTime(addOrderReq.getStartTime())
                    .worker(addOrderReq.getWorker())
                    .address(addOrderReq.getAddress())
                    .build();
            orderMapper.addOrder(addOrder);

            BigDecimal balance = userMapper.getBalanceById(userId);
            BigDecimal price = userMapper.getPriceById(addOrder.getWorker());
            BigDecimal result = balance.subtract(price);
            if (result.signum() == -1) {
                return R.error(HttpStatusConstants.INTERNAL_SERVER_ERROR, "余额不足，请充值");
            }
            userMapper.setBalanceById(userId, result);

            return R.success("下单成功");
        } catch (Exception e) {
            e.printStackTrace();
            return R.error(HttpStatusConstants.INTERNAL_SERVER_ERROR, "请稍后重试");
        }
    }

    @Override
    public R<List<ListOrderResp>> getListOrderByUserId(HttpServletRequest request) {
        try {

            String openId = JwtUtil.getOpenIdFromToken(request.getHeader("Authorization").replace("Bearer ", ""));
            Integer userId = userMapper.getIdByOpenId(openId);

            List<ListOrderResp> orderRespList = orderMapper.getListOrderByUserId(userId).stream()
                    .map(order -> {
                        Integer employeeId = order.getWorker();
                        String customerName = userMapper.getUsernameById(order.getUserId());
                        String workerName = userMapper.getUsernameById(employeeId);
                        BigDecimal price = userMapper.getPriceById(employeeId);
                        String servicePic = conEmployeeServiceMapper.getServicePicByUserId(employeeId);

                        return ListOrderResp.builder()
                                .id(order.getId())
                                .servicePic(servicePic)
                                .customerName(customerName)
                                .worker(employeeId)
                                .workerName(workerName)
                                .price(price)
                                .startTime(order.getStartTime())
                                .status(order.getStatus())
                                .address(order.getAddress())
                                .commented(order.isCommented())
                                .reback(order.isReback())
                                .orderType(true)
                                .build();
                    })
                    .collect(Collectors.toList());
            List<ListOrderResp> appointmentRespList = appointmentMapper.getListAppointmentByApplicantId(userId).stream()
                    .map(appointment -> {
                        Integer employeeId = appointment.getApproverId();
                        String customerName = userMapper.getUsernameById(appointment.getApplicantId());
                        String workerName = userMapper.getUsernameById(employeeId);
                        BigDecimal price = userMapper.getPriceById(employeeId);
                        String servicePic = conEmployeeServiceMapper.getServicePicByUserId(employeeId);

                        return ListOrderResp.builder()
                                .id(appointment.getId())
                                .servicePic(servicePic)
                                .customerName(customerName)
                                .worker(employeeId)
                                .workerName(workerName)
                                .price(price)
                                .startTime(appointment.getAppointmentTime())
                                .status(appointment.getStatus())
                                .address(appointment.getAddress())
                                .commented(appointment.isCommented())
                                .reback(appointment.isReback())
                                .orderType(false)
                                .build();
                    })
                    .collect(Collectors.toList());

            List<ListOrderResp> respList = Stream.concat(orderRespList.stream(), appointmentRespList.stream())
                    .collect(Collectors.toList());

            return R.success(respList);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error(HttpStatusConstants.INTERNAL_SERVER_ERROR, "");
        }
    }

    @Override
    public R<String> completeOrder(Integer orderId) {
        try {
            orderMapper.completeOrder(orderId);
            return R.success();
        } catch (Exception e) {
            return R.error(HttpStatusConstants.INTERNAL_SERVER_ERROR, "");
        }
    }

    @Override
    public R<List<ListOrderResp>> pendingOrderList(HttpServletRequest request) {
        try {
            String openId = JwtUtil.getOpenIdFromToken(request.getHeader("Authorization").replace("Bearer ", ""));
            Integer userId = userMapper.getIdByOpenId(openId);

            List<ListOrderResp> orderRespList = orderMapper.getListOrderInPendingByUserId(userId).stream()
                    .map(order -> {
                        Integer employeeId = order.getWorker();
                        String customerName = userMapper.getUsernameById(order.getUserId());
                        String workerName = userMapper.getUsernameById(employeeId);
                        BigDecimal price = userMapper.getPriceById(employeeId);
                        String servicePic = conEmployeeServiceMapper.getServicePicByUserId(employeeId);

                        return ListOrderResp.builder()
                                .id(order.getId())
                                .servicePic(servicePic)
                                .customerName(customerName)
                                .worker(employeeId)
                                .workerName(workerName)
                                .price(price)
                                .startTime(order.getStartTime())
                                .status(order.getStatus())
                                .address(order.getAddress())
                                .commented(order.isCommented())
                                .reback(order.isReback())
                                .orderType(true)
                                .build();
                    })
                    .collect(Collectors.toList());
            List<ListOrderResp> appointmentRespList = appointmentMapper
                    .getListAppointmentInPendingByApplicantId(userId).stream()
                    .map(appointment -> {
                        Integer employeeId = appointment.getApproverId();
                        String customerName = userMapper.getUsernameById(appointment.getApplicantId());
                        String workerName = userMapper.getUsernameById(employeeId);
                        BigDecimal price = userMapper.getPriceById(employeeId);
                        String servicePic = conEmployeeServiceMapper.getServicePicByUserId(employeeId);

                        return ListOrderResp.builder()
                                .id(appointment.getId())
                                .servicePic(servicePic)
                                .customerName(customerName)
                                .worker(employeeId)
                                .workerName(workerName)
                                .price(price)
                                .startTime(appointment.getAppointmentTime())
                                .status(appointment.getStatus())
                                .address(appointment.getAddress())
                                .commented(appointment.isCommented())
                                .reback(appointment.isReback())
                                .orderType(false)
                                .build();
                    })
                    .collect(Collectors.toList());

            List<ListOrderResp> respList = Stream.concat(orderRespList.stream(), appointmentRespList.stream())
                    .collect(Collectors.toList());

            return R.success(respList);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error(HttpStatusConstants.INTERNAL_SERVER_ERROR, "");
        }
    }

    @Override
    public R<List<ListOrderResp>> progressOrderList(HttpServletRequest request) {
        try {
            String openId = JwtUtil.getOpenIdFromToken(request.getHeader("Authorization").replace("Bearer ", ""));
            Integer userId = userMapper.getIdByOpenId(openId);

            List<ListOrderResp> orderRespList = orderMapper.getListOrderInProgressByUserId(userId).stream()
                    .map(order -> {
                        Integer employeeId = order.getWorker();
                        String customerName = userMapper.getUsernameById(order.getUserId());
                        String workerName = userMapper.getUsernameById(employeeId);
                        BigDecimal price = userMapper.getPriceById(employeeId);
                        String servicePic = conEmployeeServiceMapper.getServicePicByUserId(employeeId);

                        return ListOrderResp.builder()
                                .id(order.getId())
                                .servicePic(servicePic)
                                .customerName(customerName)
                                .worker(employeeId)
                                .workerName(workerName)
                                .price(price)
                                .startTime(order.getStartTime())
                                .status(order.getStatus())
                                .address(order.getAddress())
                                .commented(order.isCommented())
                                .orderType(true)
                                .build();
                    })
                    .collect(Collectors.toList());
            List<ListOrderResp> appointmentRespList = appointmentMapper
                    .getListAppointmentInProgressByApplicantId(userId).stream()
                    .map(appointment -> {
                        Integer employeeId = appointment.getApproverId();
                        String customerName = userMapper.getUsernameById(appointment.getApplicantId());
                        String workerName = userMapper.getUsernameById(employeeId);
                        BigDecimal price = userMapper.getPriceById(employeeId);
                        String servicePic = conEmployeeServiceMapper.getServicePicByUserId(employeeId);

                        return ListOrderResp.builder()
                                .id(appointment.getId())
                                .servicePic(servicePic)
                                .customerName(customerName)
                                .worker(employeeId)
                                .workerName(workerName)
                                .price(price)
                                .startTime(appointment.getAppointmentTime())
                                .status(appointment.getStatus())
                                .address(appointment.getAddress())
                                .commented(appointment.isCommented())
                                .orderType(false)
                                .build();
                    })
                    .collect(Collectors.toList());

            List<ListOrderResp> respList = Stream.concat(orderRespList.stream(), appointmentRespList.stream())
                    .collect(Collectors.toList());

            return R.success(respList);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error(HttpStatusConstants.INTERNAL_SERVER_ERROR, "");
        }
    }

    @Override
    public R<String> orderReback(Integer orderId, HttpServletRequest request) {
        try {
            String openId = JwtUtil.getOpenIdFromToken(request.getHeader("Authorization").replace("Bearer ", ""));
            Integer userId = userMapper.getIdByOpenId(openId);
            rebackMapper.addReback(orderId, userId);
            orderMapper.updateReback(userId);
            return R.success();
        } catch (Exception e) {
            e.printStackTrace();
            R.error(HttpStatusConstants.INTERNAL_SERVER_ERROR, "");
        }
        return null;
    }

    @Override
    public R<List<ListOrderResp>> employeeOrderList(HttpServletRequest request) {
        try {
            Integer userId = JwtUtil.getUserIdFromToken(request.getHeader("Authorization").replace("Bearer ", ""));

            List<ListOrderResp> orderRespList = orderMapper.getListOrderByWorker(userId).stream()
                    .map(order -> {
                        String customerName = userMapper.getUsernameById(order.getUserId());
                        String workerName = userMapper.getUsernameById(userId);
                        BigDecimal price = userMapper.getPriceById(userId);
                        String servicePic = conEmployeeServiceMapper.getServicePicByUserId(userId);
                        String phone = userMapper.getPhoneById(order.getUserId());
                        String customerAvatar = userMapper.getUserAvatarById(order.getUserId());

                        return ListOrderResp.builder()
                                .id(order.getId())
                                .servicePic(servicePic)
                                .customerId(order.getUserId())
                                .customerName(customerName)
                                .worker(userId)
                                .workerName(workerName)
                                .price(price)
                                .startTime(order.getStartTime())
                                .status(order.getStatus())
                                .address(order.getAddress())
                                .phone(phone)
                                .orderType(true)
                                .customerAvatar(customerAvatar)
                                .build();
                    })
                    .collect(Collectors.toList());
            List<ListOrderResp> appointmentRespList = appointmentMapper
                    .getListAppointmentByApproverId(userId).stream()
                    .map(appointment -> {
                        String customerName = userMapper.getUsernameById(appointment.getApplicantId());
                        String workerName = userMapper.getUsernameById(userId);
                        BigDecimal price = userMapper.getPriceById(userId);
                        String servicePic = conEmployeeServiceMapper.getServicePicByUserId(userId);
                        String phone = userMapper.getPhoneById(appointment.getApplicantId());
                        String customerAvatar = userMapper.getUserAvatarById(appointment.getApplicantId());

                        return ListOrderResp.builder()
                                .id(appointment.getId())
                                .servicePic(servicePic)
                                .customerId(appointment.getApplicantId())
                                .customerName(customerName)
                                .worker(userId)
                                .workerName(workerName)
                                .price(price)
                                .startTime(appointment.getAppointmentTime())
                                .status(appointment.getStatus())
                                .address(appointment.getAddress())
                                .commented(appointment.isCommented())
                                .phone(phone)
                                .customerAvatar(customerAvatar)
                                .build();
                    })
                    .collect(Collectors.toList());

            List<ListOrderResp> respList = Stream.concat(orderRespList.stream(), appointmentRespList.stream())
                    .collect(Collectors.toList());

            return R.success(respList);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error(HttpStatusConstants.INTERNAL_SERVER_ERROR, "");
        }
    }

    @Override
    public R<String> progressOrder(Integer orderId) {
        orderMapper.progressOrder(orderId);
        return R.success();
    }

    @Override
    public R<List<ListOrderResp>> searchOrderListByDate(String startDate, String endDate, HttpServletRequest request) {
        try {
            Integer userId = JwtUtil.getUserIdFromToken(request.getHeader("Authorization").replace("Bearer ", ""));

            List<ListOrderResp> orderRespList = orderMapper.getListOrderByWorkerAndDate(userId, startDate, endDate).stream()
                    .map(order -> {
                        String customerName = userMapper.getUsernameById(order.getUserId());
                        String workerName = userMapper.getUsernameById(userId);
                        BigDecimal price = userMapper.getPriceById(userId);
                        String servicePic = conEmployeeServiceMapper.getServicePicByUserId(userId);
                        String phone = userMapper.getPhoneById(order.getUserId());
                        String customerAvatar = userMapper.getUserAvatarById(order.getUserId());

                        return ListOrderResp.builder()
                                .id(order.getId())
                                .servicePic(servicePic)
                                .customerName(customerName)
                                .worker(userId)
                                .workerName(workerName)
                                .price(price)
                                .startTime(order.getStartTime())
                                .status(order.getStatus())
                                .address(order.getAddress())
                                .phone(phone)
                                .orderType(true)
                                .customerAvatar(customerAvatar)
                                .build();
                    })
                    .collect(Collectors.toList());
            List<ListOrderResp> appointmentRespList = appointmentMapper
                    .getListAppointmentByApproverIdAndDate(userId, startDate, endDate).stream()
                    .map(appointment -> {
                        String customerName = userMapper.getUsernameById(appointment.getApplicantId());
                        String workerName = userMapper.getUsernameById(userId);
                        BigDecimal price = userMapper.getPriceById(userId);
                        String servicePic = conEmployeeServiceMapper.getServicePicByUserId(userId);
                        String phone = userMapper.getPhoneById(appointment.getApplicantId());
                        String customerAvatar = userMapper.getUserAvatarById(appointment.getApplicantId());

                        return ListOrderResp.builder()
                                .id(appointment.getId())
                                .servicePic(servicePic)
                                .customerName(customerName)
                                .worker(userId)
                                .workerName(workerName)
                                .price(price)
                                .startTime(appointment.getAppointmentTime())
                                .status(appointment.getStatus())
                                .address(appointment.getAddress())
                                .commented(appointment.isCommented())
                                .phone(phone)
                                .customerAvatar(customerAvatar)
                                .build();
                    })
                    .collect(Collectors.toList());

            List<ListOrderResp> respList = Stream.concat(orderRespList.stream(), appointmentRespList.stream())
                    .collect(Collectors.toList());

            return R.success(respList);
        } catch (Exception e) {
            e.printStackTrace();
            return R.error(HttpStatusConstants.INTERNAL_SERVER_ERROR, "");
        }
    }
}
